import * as React from 'react'
import { isFunc, assign, browser } from 'muka'
import { getClassName } from '../utils'

interface IProps {
    className?: string
    style?: React.CSSProperties
    data: any[]
    EmptyShowHeader?: boolean
    renderItem: (data?: any, index?: number) => JSX.Element
    ListEmptyComponent?: JSX.Element | JSX.ElementClass
    ListHeaderComponent?: JSX.Element | JSX.ElementClass
    height?: number | string
    distance?: number
    onRefresh?: (finishLoad: () => void) => void
}

interface IState {
    status: boolean
    loading: boolean
}

export default class FlatList extends React.Component<IProps, IState> {

    public static defaultProps = {
        data: [],
        EmptyShowHeader: true
    }

    public state = {
        status: false,
        loading: false
    }

    public render() {
        const { className, style, height } = this.props
        const styles: React.CSSProperties = assign(style, { height })
        return (
            <div
                className={getClassName('flat_list', className)}
                style={styles}
            >
                {this.getHeader()}
                {this.getChildren()}
            </div>
        )
    }

    public componentWillReceiveProps() {
        this.setState({
            status: true
        })
    }

    public componentDidMount() {
        window.addEventListener('scroll', this.monitorCall)
        const { onRefresh } = this.props
        if (isFunc(onRefresh)) {
            onRefresh(this.finishLoad)
        }
    }

    public componentWillUnmount() {
        window.removeEventListener('scroll', this.monitorCall)
    }

    public finishLoad = () => {
        this.setState({
            loading: false
        })
    }

    public stopLoad = () => {
        this.setState({
            loading: true
        })
    }

    private monitorCall = () => {
        const { loading } = this.state
        if (loading) {
            return
        }
        let top = (document.documentElement.scrollTop || document.body.scrollTop) + browser.GL_SC_HEIGHT
        const scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight
        const { distance, onRefresh } = this.props
        if (scrollHeight <= browser.GL_SC_HEIGHT) { return }
        if (scrollHeight - top < (distance || 200)) {
            if (isFunc(onRefresh)) {
                onRefresh(this.finishLoad)
                this.setState({
                    loading: true
                })
            }
        }
    }

    private getHeader(): JSX.Element | JSX.ElementClass | undefined {
        const { data, EmptyShowHeader, ListHeaderComponent } = this.props
        if (data.length) {
            return ListHeaderComponent
        }
        if (EmptyShowHeader) {
            return ListHeaderComponent
        }
        return
    }

    private getChildren(): JSX.Element[] | JSX.Element | JSX.ElementClass | undefined {
        const { data, renderItem, ListEmptyComponent } = this.props
        const { status } = this.state
        if (data.length) {
            return data.map((item: any, index: number) => {
                if (isFunc(renderItem)) {
                    return renderItem(item, index)
                }
                return <div key={index} />
            })
        }
        if (status) {
            return ListEmptyComponent
        }
        return
    }
}